<?php

namespace App\Api\Controllers\v1;

use App\Api\Models\Config;
use App\Http\Controllers\ApiController;
use App\Http\Library\Map;
use App\Http\Requests\PayServiceRequest;
use App\Http\Response\ApiResponse;
use App\Models\PaymentOrder;
use App\Models\Service;
use App\Models\ServiceOrder;
use App\Models\UcService;
use App\Models\User;
use App\Models\UserCar;
use App\Models\UserCard;
use App\Models\UserCoupon;
use App\Models\UserMoney;
use App\Models\Worker;
use App\Services\OrderService;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;

use hg\apidoc\annotation as Apidoc;

/**
 * 洗车预约接口
 * @Apidoc\Group("user")
 * @Apidoc\Sort(1)
 */
class AppointController extends ApiController
{

    /**
     * 查询服务价格-改 去掉经纬度参数
     * @Apidoc\Url("/api/v1/appoint/servicePrice")
     * @Apidoc\Method("POST")
     * @Apidoc\Param("service_id", type="int", require="true", desc="服务ID", default=""),
     * @Apidoc\Param("car_id", type="int", desc="车辆ID", require=false,  default="")
     */
    public function servicePrice(): ApiResponse
    {
        $data = Service::getPrice($this->user_id);
        return $this->response()->data($data);
    }

    /**
     * 预约服务接口
     * @Apidoc\Url("/api/v1/appoint/payService")
     * @Apidoc\Method("POST")
     * @Apidoc\Param("pay_way", type="int", require="true", desc="支付方式:0=余额支付,1=微信支付,2=洗车卡次数",  default="0")
     * @Apidoc\Param("service_id", type="int", require="true", desc="服务ID", default=""),
     * @Apidoc\Param("worker_id", type="int", require="false", desc="师傅ID,默认值0", default="0"),
     * @Apidoc\Param("appoint_time", type="string", require="true", desc="上面时间,默认值,0为立即上门,日期时间",  default="0")
     * @Apidoc\Param("car_id", type="int", desc="车辆ID", require="true",  default="")
     * @Apidoc\Param("address", type="string", require="true", desc="详细地址",  default="")
     * @Apidoc\Param("user_coupon_id", type="int", require="false", desc="用户优惠券ID",  default="0")
     * @Apidoc\Param("user_card_id", type="int", require="false", desc="用户洗车卡ID",  default="0")
     * @Apidoc\Param("remark", type="string", require="false", desc="备注信息",  default="")
     * @Apidoc\Param(ref="paramLongLat")
     * @Apidoc\Returned("order_id",desc="订单ID")
     */
    public function payService(PayServiceRequest $request){
        $params = $request->validated();
        return $this->wechatPay(function ($out_trade_no,$openid,$user_id) use ($params) {
            $worker_id = $params['worker_id'];
            $appoint_time = $params['appoint_time'];
            if($appoint_time){
                if ($worker_id){
                    $order = ServiceOrder::query()
                        ->where("worker_id",$worker_id)
                        ->where("user_id",$user_id)
                        ->where("status","<",2)->first();
                    if ($order){
                        $appointDates = explode(" ",$appoint_time);
                        $appointTimes = explode("-",$appointDates[1]);
                        $appoint_date = $appointDates[0];
                        $start = Carbon::parse($appoint_date." ".$appointTimes[0].":00");
                        $end = Carbon::parse($appoint_date." ".$appointTimes[1].":00");
//                        2023-11-04 15:00-16:00
                        $a_time = $order->appoint_time;
                        if ($a_time){
                            $dates = explode(" ",$a_time);
                            $times = explode("-",$dates[1]);
                            $a_date = $dates[0];
                            $start_time = Carbon::parse($a_date." ".$times[0].":00");
                            $end_time = Carbon::parse($a_date." ".$times[1].":00");
                            // 师傅的时间 大于 预约的时间
                            $isRight = Carbon::parse($start_time)->gt($start);
                            $isLeft = Carbon::parse($end_time)->lt($end);
                            if($isLeft&&$isRight){
                                throw new Exception("此师傅忙碌中,请更换师傅或者更换1小时后的时间段!");
                            }else{
                                if (now()->gt($start)){
                                    throw new Exception("此师傅忙碌中,请更换师傅或者更换1小时后的时间段!");
                                }else{
                                    if($start->diffInHours(now())<=1){
                                        throw new Exception("此师傅忙碌中,请更换师傅或者更换1小时后的时间段!");
                                    }
                                }

                            }
                        }else{
                            $now = now();
                            $start_time = Carbon::parse($order->created_at);
                            // 师傅的时间 大于 预约的时间
                            $isLeft = Carbon::parse($order->created_at)->gt($end);
                            if($isLeft||$now->gt($start)){
                                throw new Exception("此师傅忙碌中,请更换师傅或者更换1小时后的时间段!");
                            }else{
                                if($start->diffInHours(now())<=1){
                                    throw new Exception("此师傅忙碌中,请更换师傅或者更换1小时后的时间段!");
                                }
                            }
                        }
                    }
                }
            }else{
                if ($worker_id){
                    $order = ServiceOrder::query()
                        ->where("appoint_time",0)
                        ->where("worker_id",$worker_id)
                        ->where("user_id",$user_id)
                        ->where("status","<",2)
                        ->exists();
                    if ($order){
                        throw new Exception("此师傅忙碌中,请更换师傅或者更换1小时后的时间段!");
                    }
                }
            }
            $user = User::whereId($user_id)->first();
            $info = Service::getPrice($user_id);
            $id = $params['service_id'];
            $user_coupon_id = $params['user_coupon_id'];
            $service = Service::find($id,['id','shop_id','cid','title','subtitle','image','price']);
            if (!$service){
                throw new Exception("暂无此服务信息!");
            }
            $shop_id = $service->shop_id;
            $isDiscount = false;
            $isMemberPrice = false;
            $discount = 0;
            $pay_way = $params['pay_way']??0;
            if ($pay_way==2){
                if (!isset($params['user_card_id'])){
                    throw new Exception("请选择服务洗车卡!");
                }
                $userCard = UserCard::query()->where("id",$params['user_card_id'])->first();
                if (!$userCard){
                    throw new Exception("请选择服务洗车卡!");
                }
                $start_time = $userCard->start_time;
                $end_time = $userCard->end_time;
                $isRight1 = Carbon::parse($start_time)->lt(now());
                $isRight2 = Carbon::parse($end_time)->gt(now());
                if (!($isRight1||$isRight2)){
                    throw new Exception("请选择有效的服务洗车卡!");
                }
                $s_id = $userCard->range?$params['service_id']:0;
                $us = UcService::query()
                    ->where("user_card_id",$userCard->id)
                    ->where("user_id",$this->user_id)
                    ->where("car_id",$params['car_id'])
                    ->where("service_id",$s_id)
                    ->where("shop_id",$shop_id)
                    ->first();
                if ($us){
                    if ($us->number==0){
                        $discount = $us->discount/10;
                        if ($discount==1){
                            $isMemberPrice = true;
                        }
                        $isDiscount = true;
                    }
                }else{
                    throw new Exception("此卡暂无此洗车服务!");
                }
            }
            $car = $info['car'];
            if (!$car){
                throw new Exception("暂无此车辆信息!");
            }
            $coupon_price = 0;
            $map = new Map();
            $address = $map->getAddress($params['longitude'],$params['latitude']);
            if (!$address||!$address['address']){
                throw new Exception("定位错误,请重新定位!");
            }
            list($province_id, $city_id, $district_id) = OrderService::findAddressIds($address);
            $params['province_id'] = $province_id;
            $params['city_id'] = $city_id;
            $params['district_id'] = $district_id;
            $price = floatval($info['price']);
            $member_price = floatval($info['member_price']);
            if ($user_coupon_id){
                $userCoupon = UserCoupon::whereId($user_coupon_id)->first();
                if ($userCoupon){
                    if (!$userCoupon->mode){
                        $range = $userCoupon->range;
                        $full_price = $userCoupon->full_price;
                        $coupon_price = $userCoupon->price;
                        if ($range==1){
                            if ($service->cid!=$userCoupon->cid){
                                throw new Exception("优惠券使用条件不足!");
                            }
                        }elseif ($range==2){
                            if ($id!=$userCoupon->service_id){
                                throw new Exception("优惠券使用条件不足!");
                            }
                        }
                        if ($price<$full_price){
                            throw new Exception("优惠券使用条件不足!");
                        }
                        if ($price<$coupon_price){
                            $coupon_price = $price;
                        }
                    }
                }
            }
            $amount = $price - $coupon_price;
            if ($pay_way==2){
                if ($isDiscount&&$discount>0){
                    if ($discount==1&&$isMemberPrice){
                        $amount = $member_price;
                    }else{
                        $amount = $amount*$discount;
                    }
                }elseif (!$isDiscount){
                    $amount = 0;
                }
            }elseif ($pay_way == 0){
                $userAmount = floatval($user->money);
                if ($userAmount<$amount){
                    return  [
                        'response'=>$this->response()->error("余额不足,请先充值!")
                    ];
                }
            }
            $amount = round($amount,2);
            $params['user_id'] = $user_id;
            $params['shop_id'] = $shop_id;
            $params['amount'] = $amount;
            $params['discount'] = $discount;
            $params['coupon_price'] = $coupon_price;
            $params['service'] = $service;
            $params['car'] = $car;
            $params['info'] = $info;
            $params['order_id'] = $out_trade_no;
            $params['isDiscount'] = $isDiscount;
            OrderService::addServiceOrder($user_id,$out_trade_no,$amount, $pay_way,$pay_way?$params:['shop_id'=>$shop_id]);
            if (($pay_way==1||$isDiscount)&&$amount){
                $notify_url = route("api.v1.notify",['type'=>2]);
                $body = "洗车服务购买";
                return PaymentOrder::getPayData($openid,$body,$out_trade_no,$amount,$notify_url);
            }else{
                ServiceOrder::addOrder($params);
                return [
                    'response'=>$this->response()->success("下单成功")->data(['order_id'=>$out_trade_no])
                ];
            }
        });
    }

    /**
     * 洗车服务订单列表
     * @Apidoc\Url("/api/v1/appoint/orders")
     * @Apidoc\Method("GET")
     * @Apidoc\Query("type",type="int", require=false, desc="0=用户端订单列表,1=师傅端订单列表", default="0")
     * @Apidoc\Query("status",type="int", require=false, desc="状态:-1=全部,0=待上门,1=服务中,2=已完成,3=已评价,4=已取消", default="-1")
     * @Apidoc\Query("longitude",type="string", require=false, desc="经度", default="")
     * @Apidoc\Query("latitude",type="string", require=false, desc="纬度", default="")
     * @Apidoc\Query(ref="queryPage")
     * @Apidoc\Returned(ref="listResult")
     */
    public function orders(): ApiResponse
    {
        $data = ServiceOrder::getList($this->user_id, $this->worker_id);
        return $this->response()->data($data);
    }

    /**
     * 洗车服务订单状态的数量
     * @Apidoc\Url("/api/v1/appoint/orderStatusNum")
     * @Apidoc\Method("GET")
     * @Apidoc\Returned("options",type="array")
     */
    public function orderStatusNum(): ApiResponse
    {
        $data = ServiceOrder::getStatusNums($this->worker_id);
        return $this->response()->data($data);
    }


    /**
     * 洗车订单详情
     * @Apidoc\Url("/api/v1/appoint/detail/:order_id")
     * @Apidoc\Method("GET")
     * @Apidoc\RouteParam("order_id",type="string", require=true, desc="订单号")
     * @Apidoc\Returned(ref="detail")
     * @Apidoc\Returned("detail",type="Object", @Apidoc\Returned(ref="App\Models\ServiceOrder"))
     */
    public function detail(Request $request): ApiResponse
    {
        $order_id = $request->route('order_id');
        $worker_id = $this->worker_id;
        $result = ServiceOrder::getDetail($order_id, $worker_id);
        return $this->response()->data($result);
    }


    /**
     * 服务取消操作
     * @Apidoc\Url("/api/v1/appoint/cancel/:order_id")
     * @Apidoc\Method("POST")
     * @Apidoc\RouteParam("order_id",type="string", require=true, desc="订单号")
     */
    public function cancel(Request $request): ApiResponse
    {
        $order_id = $request->route("order_id");
        $serviceOrder = ServiceOrder::whereOrderId($order_id)->first();
        if (!$serviceOrder){
            return $this->response()->error('暂无此订单信息!');
        }
        if ($serviceOrder->appoint_time){
            $hours = Config::getName("cancel_hours");
            $cancel_hours = intval($hours)*3600;
            $appoint_time = explode(" ",$serviceOrder->appoint_time);
            $hoursTime = explode("-",$appoint_time[1]);
            $appointTime = $appoint_time[0].$hoursTime[0].":00";
            $diffSeconds = Carbon::parse($appointTime)->diffInSeconds(now());
            if (($diffSeconds-$cancel_hours)<=0){
                return $this->response()->error("预约时间前{$hours}小时不能取消订单!");
            }
        }
        if ($serviceOrder->status==1){
            return $this->response()->error('服务进行中,不可取消!');
        }
        if ($serviceOrder->status==2){
            return $this->response()->error('服务已完成,不可取消!');
        }
        if ($serviceOrder->status==3){
            return $this->response()->error('服务已评价,不可取消!');
        }
        $serviceOrder->is_apply = 1;
        $res = $serviceOrder->save();
        if ($res){
            return $this->response()->success("提交申请成功");
        }else{
            return $this->response()->error("提交申请失败");
        }
    }

    /**
     * 确认上门到达
     * @Apidoc\Url("/api/v1/appoint/arrive")
     * @Apidoc\Method("POST")
     * @Apidoc\Param("order_id",type="string", require=true, desc="订单号")
     * @Apidoc\Param("info1",type="object", require=true, desc="确认时环车检查信息",
     *    @Apidoc\Param("images",type="array", require=true, desc="图片资源组"),
     *    @Apidoc\Param("content",type="string", require=true, desc="信息内容")
     * )
     */
    public function arrive(Request $request): ApiResponse
    {
        $order_id = $request->post("order_id");
        $info1 = $request->post("info1");
        if (!$info1||!$info1['images']||!$info1['content']){
            return $this->response()->error('请填完整环车检查信息!');
        }
        $order = ServiceOrder::whereOrderId($order_id)->first();
        if (!$order){
            return $this->response()->error('此服务订单不存在!');
        }
        if ($order->status==1){
            return $this->response()->error('此服务正在服务中!');
        }
        if ($order->status==2){
            return $this->response()->error('此服务已完成!');
        }
        if ($order->status==3){
            return $this->response()->error('此服务已评价!');
        }
        if ($order->status==4){
            return $this->response()->error('此订单已提交取消申请!');
        }
        if ($order->status==5){
            return $this->response()->error('此订单已取消!');
        }
        $order->info1 = $info1;
        $order->status = 1;
        $order->arrive_time = now()->format("Y-m-d H:i:s");
        $order->save();
        return $this->response()->success("已到达");
    }

    /**
     * 订单确认已完成
     * @Apidoc\Url("/api/v1/appoint/confirm")
     * @Apidoc\Method("POST")
     * @Apidoc\Param("order_id",type="string", require=true, desc="订单号")
     * @Apidoc\Param("info2",type="object", require=true, desc="完成时环车检查信息",
     *    @Apidoc\Param("images",type="array", require=true, desc="图片资源组"),
     *    @Apidoc\Param("content",type="string", require=true, desc="信息内容")
     * )
     */
    public function confirm(Request $request): ApiResponse
    {
        $order_id = $request->post("order_id");
        $info2 = $request->post("info2");
        if (!$info2||!$info2['images']||!$info2['content']){
            return $this->response()->error('请填完整环车检查信息!');
        }
        $order = ServiceOrder::whereOrderId($order_id)->first();
        if (!$order){
            return $this->response()->error('此订单不存在!');
        }
        if ($order->status==4){
            return $this->response()->error('此订单已取消!');
        }
        if ($order->status==2){
            return $this->response()->error('此订单完成!');
        }
        if ($order->status!=1){
            return $this->response()->error('此订单不在服务中!');
        }
        $order->status = 2;
        $order->info2 = $info2;
        $order->finish_time = now()->format("Y-m-d H:i:s");
        $order->save();
        return $this->response()->success("已完成");
    }

    /**
     * 获取抢单订单列表
     * @Apidoc\Url("/api/v1/appoint/snatchOrders")
     * @Apidoc\Method("GET")
     * @Apidoc\Query(ref="queryPage")
     * @Apidoc\Query(ref="queryLongLat")
     * @Apidoc\Returned(ref="listResult")
     */
    public function snatchOrders(): ApiResponse
    {
        $data = ServiceOrder::getDataList($this->user_id);
        return $this->response()->data($data);
    }

    /**
     * 洗车小哥接单接口
     * @Apidoc\Url("/api/v1/appoint/receive/:order_id")
     * @Apidoc\Method("POST")
     * @Apidoc\RouteParam("order_id", type="string", require="true", desc="订单号", default=""),
     */
    public function receive(Request $request): ApiResponse
    {
        $order_id = $request->route("order_id");
        $order = ServiceOrder::whereOrderId($order_id)->first();
        if (!$order){
            return $this->response()->error("找不到此订单!");
        }
        if ($order->worker_id&&$order->receive_time){
            return $this->response()->error("此订单已经被接单了!");
        }
        $worker = Worker::whereUserId($this->user_id)->first();
        if (!$worker){
            return $this->response()->error("不是洗车小哥,无法接单!");
        }
        $order->worker_id = $worker->id;
        $order->shop_id = $worker->shop_id;
        $order->receive_time = now()->format("Y-m-d H:i:s");
        $res = $order->save();
        if ($res){
            return $this->response()->success("接单成功");
        }else{
            return $this->response()->error("接单失败!");
        }
    }

    /**
     * 用户端确认已完成
     * @Apidoc\Url("/api/v1/appoint/finish/:order_id")
     * @Apidoc\Method("POST")
     * @Apidoc\RouteParam("order_id", type="string", require="true", desc="订单号", default=""),
     */
    public function finish(Request $request): ApiResponse
    {
        $order_id = $request->route("order_id");
        $order = ServiceOrder::whereOrderId($order_id)->first();
        if (!$order){
            return $this->response()->error('此订单不存在!');
        }
        if ($order->status==4){
            return $this->response()->error('此订单已取消!');
        }
        if ($order->state){
            return $this->response()->error('此订单完成!');
        }
        $order->state = 1;
        $order->finish_time = now()->format("Y-m-d H:i:s");
        $order->save();
        return $this->response()->success("已完成");
    }

}
